package com.xw.class12;

import java.util.ArrayList;

/**
 * @author XW
 * @data 2023/8/23 14:35
 * @description 判断一颗树是否是搜索二叉树
 *              定义：对于任意节点X，它的子树都是搜索二叉树，并且左子树的任一值小于X的值，右子树的任一值大于X的值
 */
public class Code03_IsBST {

    static class Node{
        public int value;
        public Node left;
        public Node right;

        public Node(int value){
            this.value = value;
        }
    }

    public static boolean isBST(Node head){
        if (head == null) {
            return true;
        }
        return process(head).isBST;
    }

    private static Info process(Node head) {
        if (head == null) {
            return null;
        }
        Info left = process(head.left);
        Info right = process(head.right);
        boolean isBST = true;
        int max = head.value;
        int min = head.value;
        //违背搜索二叉树的条件
        if(null != left){
            max = Math.max(max, left.max);
            min = Math.min(min, left.min);
            if(left.max >= head.value || !left.isBST){
                isBST = false;
            }
        }
        if(null != right){
            max = Math.max(max, right.max);
            min = Math.min(min, right.min);
            if(right.min <= head.value || !right.isBST){
                isBST = false;
            }
        }
        return new Info(isBST,max,min);
    }

    static class Info{
        public boolean isBST;
        public int max;
        public int min;

        public Info(boolean isBST,int max,int min){
            this.isBST = isBST;
            this.max = max;
            this.min = min;
        }
    }
    
    //测试
    public static boolean isBST1(Node head) {
        if (head == null) {
            return true;
        }
        ArrayList<Node> arr = new ArrayList<>();
        in(head, arr);
        for (int i = 1; i < arr.size(); i++) {
            if (arr.get(i).value <= arr.get(i - 1).value) {
                return false;
            }
        }
        return true;
    }

    public static void in(Node head, ArrayList<Node> arr) {
        if (head == null) {
            return;
        }
        in(head.left, arr);
        arr.add(head);
        in(head.right, arr);
    }

    // for test
    public static Node generateRandomBST(int maxLevel, int maxValue) {
        return generate(1, maxLevel, maxValue);
    }

    // for test
    public static Node generate(int level, int maxLevel, int maxValue) {
        if (level > maxLevel || Math.random() < 0.5) {
            return null;
        }
        Node head = new Node((int) (Math.random() * maxValue));
        head.left = generate(level + 1, maxLevel, maxValue);
        head.right = generate(level + 1, maxLevel, maxValue);
        return head;
    }

    public static void main(String[] args) {
        int maxLevel = 4;
        int maxValue = 100;
        int testTimes = 1000000;
        for (int i = 0; i < testTimes; i++) {
            Node head = generateRandomBST(maxLevel, maxValue);
            if (isBST1(head) != isBST(head)) {
                System.out.println("Oops!");
                printTreeNode(head);
                isBST(head);

                System.out.println();
            }
        }
        System.out.println("finish!");
    }

    private static void printTreeNode(Node head) {
        if(null == head){
            return;
        }
        System.out.print(head.value + " ");
        printTreeNode(head.left);
        printTreeNode(head.right);
    }
}
